// MSGStatusCallback.cpp: implementation of the status_call_back_impl class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "status_call_back_impl.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

status_call_back_impl::status_call_back_impl(_AFT::isession * ptr_session, aot::tt::ievent_base* ptr_notify)
{
	this->ptr_session_ = ptr_session;
	this->ptr_notify_ = ptr_notify;
	this->last_notify_time_ = 0;
	this->is_cancel_ = FALSE;
	this->i = 0;
	this->last_trans_len_ = 0;
 	this->speed_calculator_.set_sample_count(20);
	this->speed_calculator_.set_mode(speed_calculator::e_use_total_trans_size);
}


HRESULT status_call_back_impl::OnStartBinding(DWORD grfBSCOption, IBinding* pbinding)
{	
    return S_OK;
}

HRESULT status_call_back_impl::GetPriority(LONG* pnPriority) 
{
	return E_NOTIMPL;
}

HRESULT status_call_back_impl::OnLowResource(DWORD dwReserved)
{
	return E_NOTIMPL;
}

HRESULT status_call_back_impl::OnProgress(ULONG ulProgress, ULONG ulProgressMax,
									   ULONG ulStatusCode, LPCWSTR szStatusText) 
{
	DWORD cur_time = 0;

	this->ptr_session_->set_file_size(ulProgressMax);

 	if ( this->speed_calculator_.get_file_size() == 0 )
 	{
 		this->speed_calculator_.set_file_size(ulProgressMax);
 	}

	if (last_trans_len_ != ulProgress)
	{
		if ( i++ % 8 == 0 )
		{
			this->speed_calculator_.set_sample(ulProgress);

			cur_time = GetTickCount();
			if ( 0 == last_notify_time_ )
			{
				this->last_notify_time_ = cur_time;
			}

			if ( (cur_time - last_notify_time_) > 300  )
			{
				this->ptr_session_->set_transfered_size(ulProgress);
				this->ptr_session_->set_speed(this->speed_calculator_.get_speed());

				if ( this->ptr_notify_ )
				{
					this->ptr_notify_->on_notify(WM_GLB_FTC_TO_UI_PROGRESS, (WPARAM)this->ptr_session_, NULL);
				}

				this->last_notify_time_ = cur_time;
			}	
 		}
	}

	this->last_trans_len_ = ulProgress;

	if ( this->is_cancel_ )
	{
		return E_ABORT;
	}
	else
	{
		return	S_OK;
	}
}

HRESULT status_call_back_impl::OnStopBinding(HRESULT hrResult, LPCWSTR szError) 
{
   return S_OK;
}

HRESULT status_call_back_impl::GetBindInfo(DWORD* pgrfBINDF, BINDINFO* pbindinfo) 
{
	return S_OK;
}

HRESULT status_call_back_impl::OnDataAvailable(DWORD grfBSCF, DWORD dwSize, FORMATETC *pfmtetc, STGMEDIUM* pstgmed) 
{
	return S_OK;
}

HRESULT status_call_back_impl::OnObjectAvailable(REFIID riid, IUnknown* punk) 
{
	if (riid != IID_IClassFactory || punk == NULL)
		return E_INVALIDARG;

	return S_OK;
}

STDMETHODIMP status_call_back_impl::QueryInterface(REFIID iid, void **ppUnk)
{
   
	*ppUnk = NULL;

    if (iid==IID_IUnknown || iid==IID_IBindStatusCallback)	
    {
	    *ppUnk = (IBindStatusCallback*)this;
		AddRef();
		return S_OK;
	}
	else
	{
		return E_NOINTERFACE;
	}

}

STDMETHODIMP_(ULONG)  status_call_back_impl::AddRef( void) 
{
	
	return m_cRef++;
}

STDMETHODIMP_(ULONG)   status_call_back_impl::Release( void) 
{
	if (--m_cRef == 0) 
	{ 
		delete this;
		return 0;
	}
	return m_cRef; 
}

/// basic check by fan05